/*
 * $Id: InsiteAutoCheckoutSweepTask.java,v 1.12 2009/08/21 15:02:50 navdeep_mahajan Exp $
 * 
 * Copyright (C) 2006 General Electric Company. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of the General
 * Electric Company (GE). You shall not disclose this software and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with GE.
 * 
 * GE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. GE SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING, OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */
package com.ge.healthcare.autosc.processor.dispatcher.tasks;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.Properties;

import com.ge.healthcare.autosc.common.ASCLogger;
import com.ge.healthcare.autosc.common.ASCUtil;
import com.ge.healthcare.autosc.common.database.pojo.ActFileTransferDetails;
import com.ge.healthcare.autosc.common.database.pojo.ActRequestProperties;
import com.ge.healthcare.autosc.common.database.pojo.ActTask;
import com.ge.healthcare.autosc.common.exceptions.FTPCommandException;
import com.ge.healthcare.autosc.common.util.ASCFileHandler;
import com.ge.healthcare.autosc.processor.exception.IPSweepException;

/**
 * @author 212042764
 * 
 */
public class InsiteAutoCheckoutSweepTask extends IPSweepTask {
	
	private static final String PROP_END_IDENTIFIER = "]}";
	private static final String PROP_START_IDENTIFIER = "{Prop:[";
	private static String IAC_SERVICE_NAME = "continue.iac";
	private static String IAC_SERVICE_TMPL_FILE = "continue.iac.tmpl";
	public static final String SDFNR_KEY = "SDFNR";

	private Map<String, String> requestProperties = null;

	// list of properties to be transfered from the TDF file
	// into the request properties for this transaction
	private static String[][] spPropList = {
			  { "SOFTWARE_REV", "TDF_REV" }
			, { "IIP_SOFTWARE_REV", "TDF_REV" }
			, { "MODEL_TYPE", "TDF_MODEL" }
			, { "PRODUCTPHONE", "TDF_PRODUCTPHONE" }
			, { "USER1", "TDF_USER1" }
			, { "USER2", "TDF_USER2"}
	} ;
	
	/**
	 * Executes insite auto checkout task
	 * 
	 * @see com.ge.healthcare.autosc.processor.dispatcher.tasks.IPSweepTask#executeTask(com.ge.healthcare.autosc.common.database.pojo.ActTask)
	 */
	public void executeTask(ActTask task) {
		String methodName = "executeTask";
		ASCLogger.debug(this.getClass(), methodName,
				"Starting InsiteAutoCheckoutSweepTask for task:" + task);
		boolean success = false;
		this.task = task;
		try {
			this.init();
			this.validateMinimumInput();
			try {
				this.loadAutoCheckOutProperties();
				this.makeConnection();
				this.performLogin();
				this.executeInsiteAutoCheckout();
				success = true;
			} finally {
				this.ftpLogout();
				this.addChronology(success);
			}
		} finally {
			this.endLogProcessing(success);
		}
		ASCLogger.debug(this.getClass(), methodName,
				"Finished InsiteAutoCheckoutSweepTask for task:" + task);
	}

	/**
	 * Execute special processing for InsiteAutoCheckout. Send a file to the
	 * target system to be retrieved later.
	 */
	private void executeInsiteAutoCheckout() {
		File iacFile = this.getAutoCheckoutFile();
		String remoteFile = this.getSdfnrName();
		if (ASCUtil.isNullOrEmpty(remoteFile)) {
			throw new IPSweepException(new StringBuffer().append(
					"Remote file name not available").toString(),
					PRC_IAC_F_FIO_004);
		}
		try {
			this.putBinaryFile(iacFile.getAbsolutePath(), remoteFile,
					IPSWEEP_PREFIX, request.getRequestId());
		} catch (FTPCommandException ftpCommandException) {
			throw new IPSweepException(new StringBuffer().append(
					"Failed to transfer local file:").append(
					iacFile.getAbsolutePath()).append(" to remote location:")
					.append(remoteFile).toString(), PRC_IAC_F_FTP_001);
		}

	}

	/**
	 * Sets up enviornment
	 * 
	 * @see com.ge.healthcare.autosc.processor.dispatcher.tasks.IPSweepTask#setUpEnvironment()
	 */
	protected void setUpEnvironment() {
		this.jobDir = ASCUtil.getJobDir(request.getRequestId());
		new File(this.jobDir).mkdirs();
		requestProperties = requestPropertiesDAO
				.getRequestPropertiesByRequestId(request.getRequestId());
	}

	/**
	 * Validates minimum input
	 */
	private void validateMinimumInput() {
		if (ASCUtil.isNullOrEmptyMap(requestProperties)) {
			throw new IPSweepException(
					"Request Properties not found for request id:"
							+ request.getRequestId(), PRC_IAC_F_VAL_001);
		}
	}

	private void loadAutoCheckOutProperties() {
		String tdfFileName = requestProperties.get(ActRequestProperties.TDF_FILE);
		if(!ASCUtil.isNullOrEmpty(tdfFileName)) {
			Properties autoCheckOutProperties = loadAutoCheckOutProperties(tdfFileName);
			conversion(autoCheckOutProperties);
		} else {
			throw new IPSweepException("Cannot identify tdf file for task " + task, PRC_IAC_F_TDF_001);
		}
	}
	
	private void conversion(Properties prop) {
		for (int i = 0; i < spPropList.length; i++) {
			String temp = prop.getProperty(spPropList[i][0]);

            //the following if statement is a fix for the tdf
            //files received from the scanner with a line
            //of the form
            //(userX=somebody@somewhere.comLinkID=xxx)
            //the problem is that 'LinkID=xxx' is not part of
            //the userX's email address and so it has to be removed
			if((temp!=null)&&(spPropList[i][0].indexOf("USER")>=0)) {
              int badIndex = temp.indexOf("Link");
              if(badIndex>0)
                temp = temp.substring(0, badIndex);
            }

			if (temp != null) {
				this.requestProperties.put(spPropList[i][1], temp);
			}
		}
	}
	
	private Properties loadAutoCheckOutProperties(String tdfFileName) {
		FileInputStream fis = null;
		BufferedReader in = null;
		Properties prop = new Properties();

		ActFileTransferDetails ftDetail = 
			fileTransferDAO.getExternalFileTransferByRequestIdAndFileName(task.getRequestId(), tdfFileName);
		if(ftDetail != null) {
			File file = ftDetail.getFile();
			try {
				fis = new FileInputStream(file);
				in = new BufferedReader(new InputStreamReader(fis));
				String r;
				String key, value;
				for (r = in.readLine(); r != null; r = in.readLine()) {
					// Separate into before and after '='
		           	int index = r.indexOf('=');
					if (index == 0) {
						// no key, skip this line and continue with next
						continue;
					} if (index < 0) {
						// key with no value, set value to empty string
						key = r;
						value = "";
					} else {
						key = r.substring(0, index);
						value = r.substring(index + 1);
					}
					key = key.trim();
					value = value.trim();
	
					// next line if this one is empty or is a comment
					if ((key.length() <= 0) || (key.charAt(0) == '#')) {
						continue;
					}
					key = key.toUpperCase();
					prop.setProperty(key, value);
				}
			} catch (FileNotFoundException fnfe) {
				throw new IPSweepException("Cannot find TDF file  " + file.getPath(), PRC_IAC_F_TDF_002);
			} catch (IOException ioe) {
				throw new IPSweepException("Error reading TDF file " + file.getPath(), PRC_IAC_F_TDF_003);
			} finally{
				ASCFileHandler.closeInputStream(fis);
				ASCFileHandler.closeReader(in);
			}
		} else {
			throw new IPSweepException("TDF file transfer record is missing. Filename " + tdfFileName, PRC_IAC_F_TDF_004);
		}
		return prop;
	}
	
	/**
	 * Creates autocheckout file
	 * 
	 * @return
	 */
	private File getAutoCheckoutFile() {
		File iacFile = new File(this.jobDir, IAC_SERVICE_NAME);
		Object[] contents = null;
		try {
			contents = ASCFileHandler.locateAndReadFile(IAC_SERVICE_TMPL_FILE);
		} catch (FileNotFoundException fileNotFoundException) {
			throw new IPSweepException(new StringBuffer().append(
					"Failed to locate tmpl file:")
					.append(IAC_SERVICE_TMPL_FILE).toString(),
					PRC_IAC_F_FIO_002);
		} catch (IOException ioException) {
			throw new IPSweepException(new StringBuffer().append(
					"Failed to read tmpl file:").append(IAC_SERVICE_TMPL_FILE)
					.toString(), PRC_IAC_F_FIO_003);
		}
		StringBuffer iacFileContents = new StringBuffer();
		for (int iCount = 0; iCount < contents.length; iCount++) {
			iacFileContents.append(this
					.parseProperties((String) contents[iCount]));
		}
		try {
			ASCFileHandler.writeToFile(iacFile, false, iacFileContents
					.toString());
		} catch (IOException e) {
			throw new IPSweepException(new StringBuffer().append(
					"Failed to write ").append(IAC_SERVICE_NAME).append(
					" under jobdir").append(this.jobDir).toString(),
					PRC_IAC_F_FIO_001);
		}
		return iacFile;
	}

	/**
	 * Parses properties returned from template files
	 * 
	 * @param line
	 * @return
	 */
	private String parseProperties(String line) {
		if (ASCUtil.isNullOrEmpty(line)) {
			return line;
		}
		while (line.indexOf(PROP_START_IDENTIFIER) != -1) {
			String preLineContent = line.substring(0, line
					.indexOf(PROP_START_IDENTIFIER));
			String propertyName = line.substring(line
					.indexOf(PROP_START_IDENTIFIER)
					+ PROP_START_IDENTIFIER.length(), line
					.indexOf(PROP_END_IDENTIFIER));
			String postLineContent = line.substring(line
					.indexOf(PROP_END_IDENTIFIER)
					+ PROP_END_IDENTIFIER.length());
			String propertyValue = requestProperties.get(propertyName);
			line = preLineContent + propertyValue + postLineContent;
		}
		return line;
	}

	/**
	 * Extract the base file name from an 'SDFNR' property.
	 * 
	 * @param props
	 *            Properties objectpossibly containing the SDFNR value
	 * 
	 * @return The base file name of the SDFNR value, null if no such value
	 */
	private String getSdfnrName() {
		String temp = this.requestProperties.get(SDFNR_KEY);
		if (ASCUtil.isNullOrEmpty(temp)) {
			return null;
		}
		temp = temp.replace('(', ' ');
		temp = temp.replace(')', ' ');
		temp = temp.trim();
		int index = temp.indexOf(',');
		String fName = temp.substring(0, index).trim();
		if (fName.length() > 0) {
			return fName;
		}
		return null;
	}
}
